#pragma once

#include "Singleton.h"
#include "Character.h"

class MapServerProxy;

class CharacterMgr : public Singleton<CharacterMgr>
{
public:
	CharacterMgr();
	virtual ~CharacterMgr();

	bool LoadDataFromDB();
	GErrorCode UpdateCharacter(const InstPlayerOutlineInfo& info);
	GErrorCode RemoveCharacter(Character* pChar);

	Character* GetCharacter(uint32 uid) const;
	Character* GetCharacter(ObjGUID guid) const;
	Character* GetCharacterByName(const std::string& name) const;

	GErrorCode LoginCharacter(Account* pAccount, Character* pChar);
	GErrorCode LogoutCharacter(Account* pAccount, Character* pChar);

	void PushAllCharacterRankDatas();
	void NewCharacterRankData(Character* pChar);
	void UpdateCharacterRankData(Character* pChar, int subType = -1);
	void RemoveCharacterRankData(Character* pChar);
	void PackCharacterRankData(INetPacket& pck,
		Character* pChar, RANK_SUBTYPE subType, int flags = 0);

	void DisposeMapServerOffline(MapServerProxy* pMapServer);

	auto GetOnlineCharacters() const ->
		const std::unordered_map<ObjGUID, Character*>& {
		return m_OnlineCharacters;
	}
	auto GetCharacterInfoMap() const ->
		const std::unordered_map<ObjGUID, Character*>& {
		return m_CharacterInfoMap;
	}
	auto GetCharacterNameMap() const ->
		const std::unordered_map<std::string, Character*>& {
		return m_CharacterNameMap;
	}

	void UpdatePlayerLevelMax(uint32 playerLevel);
	void SyncPlayerLevelMax2MapServer(uint32 serviceId = -1) const;

	static GErrorCode CheckPlayerName(const std::string_view& name);
	static GErrorCode CheckGuildName(const std::string_view& name);

	static void InitPlayerInstance(inst_player_char& instInfo);
	static void OnCreatePlayerInstance(uint32 uid, INetStream& pck, int32 err);
	static void OnDeletePlayerInstance(uint32 uid, INetStream& pck, int32 err);

	static void SendOperating4Login(Character* pChar);
	static void SendOperating4EventActvt(
		Character* pChar, OperatingEventType eventType, params<uint32> params);
	static void SendOperatingPacket2SS(Character* pChar, const INetPacket& pck);
	static std::string PackOperatingPlayerInfo(Character* pChar);

private:
	void OnCharacterOnline(Character* pChar);
	void OnCharacterOffline(Character* pChar);

	static GErrorCode CheckCharacter(Character* pChar);

	std::unordered_map<ObjGUID, Character*> m_OnlineCharacters;
	std::unordered_map<ObjGUID, Character*> m_CharacterInfoMap;
	std::unordered_map<std::string, Character*> m_CharacterNameMap;

	uint32 m_playerLevelMax;
};

#define sCharacterMgr (*CharacterMgr::instance())
